/**
 * 增强版日志系统
 * 提供模块级别日志控制、性能监控等高级功能
 */

const path = require('path');
const loggerCore = require('./logger-core');
const { getEnvironment, getClientIP, truncateString } = require('./utils');
const config = require('../../config');

// 从logger-core获取日志级别常量
const { LOG_LEVELS, log } = loggerCore;

// 获取logger配置
const loggerConfig = config.logger || {};

// 级别映射：将字符串级别映射到数字级别（兼容log函数）
const LEVEL_TO_NUMBER = {
  [LOG_LEVELS.ERROR]: 0,
  [LOG_LEVELS.WARN]: 1,
  [LOG_LEVELS.INFO]: 2,
  [LOG_LEVELS.DEBUG]: 3
};

// 模块级别的日志级别配置
const moduleLogLevels = loggerConfig.MODULE_LOG_LEVELS || {};

// 全局日志级别
let globalLogLevel = LOG_LEVELS[loggerConfig.DEFAULT_LOG_LEVEL] || LOG_LEVELS.INFO;

// 创建一个专门用于记录配置相关信息的logger实例
// 注意：这个logger必须在getLogger函数定义之前创建，但使用getLogger的逻辑
// 为了避免循环依赖，我们直接使用log函数创建一个简单的logger实例
const configLogger = {
  info: (message, meta = {}) => {
    log(LEVEL_TO_NUMBER[LOG_LEVELS.INFO], message, {
      module: 'logger-config',
      ...meta
    });
  },
  error: (message, meta = {}) => {
    log(LEVEL_TO_NUMBER[LOG_LEVELS.ERROR], message, {
      module: 'logger-config',
      ...meta
    });
  }
};

/**
 * 获取调用方信息（文件名、行号、函数名）
 * @returns {Object} 调用方信息对象
 */
function getCallerInfo() {
  const stack = new Error().stack;
  if (!stack) return {};
  
  // 跳过前3个堆栈帧（当前函数、getLogger、实际日志调用）
  const stackLines = stack.split('\n');
  const callerLine = stackLines[3];
  if (!callerLine) return {};
  
  // 尝试提取文件路径、行号和列号
  const match = callerLine.match(/\((.*):(\d+):(\d+)\)/);
  if (!match) return {};
  
  const filePath = match[1];
  const lineNumber = match[2];
  
  // 提取文件名（不包含路径）
  const fileName = path.basename(filePath);
  
  // 尝试提取函数名，优化匿名函数检测
  let functionName = 'anonymous';
  const functionMatch = callerLine.match(/at\s+([^(\s]+)/);
  if (functionMatch) {
    functionName = functionMatch[1];
    // 清理匿名函数显示
    if (functionName.includes('anonymous')) {
      functionName = 'main';
    }
  }
  
  return {
    file: fileName,
    path: filePath,
    line: lineNumber,
    function: functionName
  };
}

/**
 * 设置全局日志级别
 * @param {string} level - 日志级别
 */
function setGlobalLogLevel(level) {
  if (Object.values(LOG_LEVELS).includes(level)) {
    globalLogLevel = level;
    configLogger.info(`Global log level set to: ${level}`);
  } else {
    configLogger.error(`Invalid log level: ${level}. Using current level: ${globalLogLevel}`);
  }
}

/**
 * 设置特定模块的日志级别
 * @param {string} moduleName - 模块名称
 * @param {string} level - 日志级别
 */
function setModuleLogLevel(moduleName, level) {
  if (Object.values(LOG_LEVELS).includes(level)) {
    moduleLogLevels[moduleName] = level;
    configLogger.info(`Module '${moduleName}' log level set to: ${level}`);
  } else {
    configLogger.error(`Invalid log level: ${level} for module: ${moduleName}`);
  }
}

/**
 * 获取模块的有效日志级别
 * @param {string} moduleName - 模块名称
 * @returns {string} 日志级别
 */
function getEffectiveLogLevel(moduleName) {
  return moduleLogLevels[moduleName] || globalLogLevel;
}

/**
 * 检查日志级别是否应该被记录
 * @param {string} level - 要记录的日志级别
 * @param {string} moduleLevel - 模块的日志级别
 * @returns {boolean} 是否应该记录
 */
function shouldLog(level, moduleLevel) {
  const levelPriority = {
    [LOG_LEVELS.ERROR]: 0,
    [LOG_LEVELS.WARN]: 1,
    [LOG_LEVELS.INFO]: 2,
    [LOG_LEVELS.DEBUG]: 3
  };
  
  return levelPriority[level] <= levelPriority[moduleLevel];
}

/**
 * 创建模块级别的logger实例
 * @param {string} moduleName - 模块名称
 * @returns {Object} logger实例
 */
function getLogger(moduleName) {
  return {
    /**
     * 记录debug级别日志
     * @param {string} message - 日志消息
     * @param {Object} meta - 附加元数据
     */
    debug: (message, meta = {}) => {
      if (shouldLog(LOG_LEVELS.DEBUG, getEffectiveLogLevel(moduleName))) {
        const callerInfo = getCallerInfo();
        log(LEVEL_TO_NUMBER[LOG_LEVELS.DEBUG], message, {
          ...meta,
          module: moduleName,
          ...callerInfo,
          correlation_id: meta.correlation_id || (global && global.correlationId) || 'unknown'
        });
      }
    },
    
    /**
     * 记录info级别日志
     * @param {string} message - 日志消息
     * @param {Object} meta - 附加元数据
     */
    info: (message, meta = {}) => {
      if (shouldLog(LOG_LEVELS.INFO, getEffectiveLogLevel(moduleName))) {
        const callerInfo = getCallerInfo();
        log(LEVEL_TO_NUMBER[LOG_LEVELS.INFO], message, {
          ...meta,
          module: moduleName,
          ...callerInfo,
          correlation_id: meta.correlation_id || (global && global.correlationId) || 'unknown'
        });
      }
    },
    
    /**
     * 记录warn级别日志
     * @param {string} message - 日志消息
     * @param {Object} meta - 附加元数据
     */
    warn: (message, meta = {}) => {
      if (shouldLog(LOG_LEVELS.WARN, getEffectiveLogLevel(moduleName))) {
        const callerInfo = getCallerInfo();
        log(LEVEL_TO_NUMBER[LOG_LEVELS.WARN], message, {
          ...meta,
          module: moduleName,
          ...callerInfo,
          correlation_id: meta.correlation_id || (global && global.correlationId) || 'unknown'
        });
      }
    },
    
    /**
     * 记录error级别日志
     * @param {string} message - 日志消息
     * @param {Error} errorObj - 错误对象（专门用于传递Error实例）
     * @param {Object} meta - 附加元数据
     */
    error: (message,meta = {}, errorObj = null) => {
      if (shouldLog(LOG_LEVELS.ERROR, getEffectiveLogLevel(moduleName))) {
        const callerInfo = getCallerInfo();
        let errorMessage = message; // 默认使用传入的消息作为错误消息
        let errorMeta = { ...meta }; // 复制元数据避免直接修改
        
        // 情况1: 提供了专门的errorObj参数（优先处理）
        if (errorObj && errorObj instanceof Error) {
          errorMessage = errorObj.message;
          errorMeta.errorStack = errorObj.stack;
          errorMeta.errorName = errorObj.name;
          // 添加错误类型的标识
          errorMeta.isErrorInstance = true;
        }
        // 情况2: 检查meta对象中的error属性（兼容现有调用方式）
        else if (meta.error instanceof Error) {
          errorMeta.errorStack = meta.error.stack;
          errorMeta.errorName = meta.error.name;
          errorMeta.errorMessageDetail = meta.error.message;
          // 保留原始error引用便于后续处理
          errorMeta.originalError = meta.error;
        }
        
        // 调用核心日志函数，传递处理后的消息和元数据
        log(LEVEL_TO_NUMBER[LOG_LEVELS.ERROR], errorMessage, {
          ...errorMeta,
          module: moduleName,
          ...callerInfo,
          correlation_id: meta.correlation_id || (global && global.correlationId) || 'unknown'
        });
      }
    },
    
    /**
     * 设置此logger实例的日志级别
     * @param {string} level - 日志级别
     */
    setLevel: (level) => {
      setModuleLogLevel(moduleName, level);
    }
  };
}

/**
 * 模块级别的请求日志中间件
 * @param {Object} options - 配置选项
 * @returns {Function} 中间件函数
 */
function createRequestLogger(options = {}) {
  const { 
    moduleName = 'http',
    logBody = true,
    logHeaders = false
  } = options;
  
  const logger = getLogger(moduleName);
  
  return (req, res, next) => {
    const startTime = Date.now();
    
    // 记录请求信息（仅记录非GET请求的body）
      const requestInfo = {
        method: req.method,
        url: req.url,
        ip: req.ip || req.connection.remoteAddress,
        userAgent: req.get('User-Agent'),
        referer: req.get('Referer'),
        clientPage: req.get('X-Client-Page'),
        userId: req.user?.id || 'unauthenticated',
        params: req.params,
        query: req.query,
        body: (req.method !== 'GET' && logBody) ? req.body : undefined,
        headers: logHeaders ? { ...req.headers } : undefined
      };
    
    logger.info('请求开始', requestInfo);
    
    // 监听响应完成
    res.on('finish', () => {
      const duration = Date.now() - startTime;
      const responseInfo = {
        ...requestInfo,
        status_code: res.statusCode,
        duration_ms: duration,
        response_size: res.get('Content-Length') || 0,
        // 添加响应时间分类
        response_time_category: duration < 100 ? 'fast' : duration < 500 ? 'normal' : duration < 1000 ? 'slow' : 'very_slow'
      };
      
      // 根据状态码选择日志级别
      if (res.statusCode >= 500) {
        logger.error('请求失败', responseInfo);
      } else if (res.statusCode >= 400) {
        logger.warn('请求警告', responseInfo);
      } else {
        logger.info('请求完成', responseInfo);
      }
    });
    
    next();
  };
}

/**
 * 模块级别的错误日志中间件
 * @param {string} moduleName - 模块名称
 * @returns {Function} 中间件函数
 */
function createErrorLogger(moduleName = 'error') {
  const logger = getLogger(moduleName);
  
  return (err, req, res, next) => {
    // 构建错误日志元数据
    const errorInfo = {
      method: req.method,
      url: req.url,
      ip: req.ip || req.connection.remoteAddress,
      userId: req.user?.id || 'unauthenticated',
      errorName: err.name,
      errorMessage: err.message,
      errorStack: err.stack,
      statusCode: err.statusCode || 500,
      // 仅在开发环境记录请求体和头信息
      ...(process.env.NODE_ENV === 'development' ? {
        requestBody: req.body,
        requestHeaders: req.headers
      } : {})
    };
    
    logger.error('Error occurred during request processing', errorInfo);
    next(err);
  };
}

module.exports = {
  // 核心功能
  getLogger,
  setGlobalLogLevel,
  setModuleLogLevel,
  getEffectiveLogLevel,
  
  // 中间件生成器
  createRequestLogger,
  createErrorLogger
};